﻿using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Tasks;

namespace ESRI.ArcGIS.Client.Async
{
    public static partial class LocatorExtensions
    {
        #region AddressesToLocations

        /// <summary>
        /// Performs a geocode search for multiple addresses.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="parameter">The parameter to configure the request.</param>
        /// <returns></returns>
        public static Task<AddressesToLocationsTaskResult> AddressesToLocationsTaskAsync(this Locator task,
            AddressesToLocationsParameter parameter)
        {
            return AddressesToLocationsTaskAsync(task, parameter, CancellationToken.None);
        }


        /// <summary>
        /// Performs a geocode search for multiple addresses.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="parameter">The parameter to configure the request.</param>
        /// <param name="cancellationToken">Cancellation token for cancelling task.</param>
        /// <returns></returns>
        public static Task<AddressesToLocationsTaskResult> AddressesToLocationsTaskAsync(this Locator task,
            AddressesToLocationsParameter parameter, CancellationToken cancellationToken)
        {
            return AddressesToLocationsTaskAsync(task, parameter.Addresses, parameter.OutSpatialReference,
                cancellationToken);
        }

        /// <summary>
        /// Performs a geocode search for multiple addresses.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="addresses">List of attributes that the geocode service will evaluate when goecoding is performed.
        /// See geocode server service definition for a list of valid attributes.</param>
        /// <param name="outSpatialReference">The spatial reference the geometry should be returned.</param>
        /// <returns></returns>
        public static Task<AddressesToLocationsTaskResult> AddressesToLocationsTaskAsync(this Locator task,
            IList<IDictionary<string, string>> addresses, SpatialReference outSpatialReference)
        {
            return AddressesToLocationsTaskAsync(task, addresses, outSpatialReference, CancellationToken.None);
        }

        /// <summary>
        /// Performs a geocode search for multiple addresses.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="addresses">List of attributes that the geocode service will evaluate when goecoding is performed.
        /// See geocode server service definition for a list of valid attributes.</param>
        /// <param name="outSpatialReference">The spatial reference the geometry should be returned.</param>
        /// <param name="cancellationToken">Cancellation token for cancelling task.</param>
        /// <returns></returns>
        public static Task<AddressesToLocationsTaskResult> AddressesToLocationsTaskAsync(this Locator task,
            IList<IDictionary<string, string>> addresses, SpatialReference outSpatialReference,
            CancellationToken cancellationToken)
        {
            return task.HandleTask<Locator, AddressesToLocationsEventArgs, AddressesToLocationsTaskResult>(
                t => t.AddressesToLocationsAsync(addresses, outSpatialReference),
                (t, e) => t.AddressesToLocationsCompleted += e,
                (t, e) => t.AddressesToLocationsCompleted -= e,
                e => new AddressesToLocationsTaskResult(e),
                cancellationToken);
        }

        #endregion

        #region Find

        /// <summary>
        /// Performs a find search using a geocode service.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="parameters">Includes text and additional options for refining or restricting search results.</param>
        /// <returns></returns>
        public static Task<LocatorFindResult> FindTaskAsync(this Locator task, LocatorFindParameters parameters)
        {
            return FindTaskAsync(task, parameters, CancellationToken.None);
        }

        /// <summary>
        /// Performs a find search using a geocode service.
        /// </summary>
        /// <param name="task"></param>
        /// <param name="parameters">Includes text and additional options for refining or restricting search results.</param>
        /// <param name="cancellationToken">Cancellation token for cancelling task.</param>
        /// <returns></returns>
        public static Task<LocatorFindResult> FindTaskAsync(this Locator task, LocatorFindParameters parameters,
            CancellationToken cancellationToken)
        {
            return task.HandleTask<Locator, LocatorFindEventArgs, LocatorFindResult>(
                t => t.FindAsync(parameters),
                (t, e) => t.FindCompleted += e,
                (t, e) => t.FindCompleted -= e,
                e => e.Result,
                cancellationToken);
        }

        #endregion

    }
}


